#include <libgen.h>
#include <time.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include "vcd-log.h"

#include "easylog/easylog.h"

int vcd_log_init_easylog(const char* logdir);
void vcd_log_easylog(int level,const char* log);
static void _vcd_log_delete_old_log(const char* logdir);

/*
default:FALSE
print log_error only:FALSE
print log debug and error:TRUE
*/
gboolean vcd_log_open_ctl = TRUE;

static gboolean g_debug_flag;
static char*    g_vcd_log_filename;

#ifdef HAVE_LOG4C

#include <log4c.h>
#include <log4c/appender_type_rollingfile.h>

static log4c_category_t *log_category = NULL;
static log4c_category_t *log_category_info = NULL;

static const char* dated_spice_format(
        const log4c_layout_t *a_layout,
        const log4c_logging_event_t *a_event)
{
    static char buffer[40960];

#ifndef _WIN32
//#ifndef __HP_cc
//#warning gmtime() routine should be defined in sd_xplatform
//#endif
    struct tm tm;
    gmtime_r(&a_event->evt_timestamp.tv_sec, &tm);
    snprintf(buffer, sizeof(buffer), "%04d%02d%02d %02d:%02d:%02d.%06ld %-5s %s\n",
             tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
             (tm.tm_hour + 8) % 24, tm.tm_min, tm.tm_sec,
             a_event->evt_timestamp.tv_usec,
             log4c_priority_to_string(a_event->evt_priority),
             a_event->evt_msg);
#else
    SYSTEMTIME stime;

//    if (FileTimeToSystemTime(&a_event->evt_timestamp, &stime)) {
//        snprintf(buffer, sizeof(buffer), "%04d%02d%02d %02d:%02d:%02d.%03ld %-6s %s\n",
//                 stime.wYear, stime.wMonth , stime.wDay,
//                 (stime.wHour + 8) % 24, stime.wMinute,
//                 stime.wSecond, stime.wMilliseconds,
//                 log4c_priority_to_string(a_event->evt_priority),
//                 a_event->evt_msg);
//    }

    struct tm *tm = localtime(&a_event->evt_timestamp.tv_sec);
    snprintf(buffer, sizeof(buffer), "%04d-%02d-%02d %02d:%02d:%02d.%06ld %-5s %s\n",
             tm->tm_year + 1900,
             tm->tm_mon + 1,
             tm->tm_mday,
             tm->tm_hour,
             tm->tm_min,
             tm->tm_sec,
             a_event->evt_timestamp.tv_usec,
             log4c_priority_to_string(a_event->evt_priority),
             a_event->evt_msg);
#endif
    return buffer;
}

const log4c_layout_type_t log4c_layout_type_spice = {
    "dated_spice_format",
    dated_spice_format,
};

static int init_dated_spice_format(void)
{
    log4c_layout_type_set(&log4c_layout_type_spice);//自定义格式类型函数指针
    return 0;
}
#endif

// ===  FUNCTION  ======================================================================
//  Name:  log_message
//  Description:  记录日志信息
//  @param priority [in]: 日志类别
//  @param file [in]: 文件
//  @param line [in]: 行
//  @param fun [in]: 函数
//  @param fmt [in]: 格式化参数
// =====================================================================================
void log_message(int priority, const char *file, int line, const char *fun, const char *fmt, ...)
{

    if(!vcd_log_open_ctl){
        fprintf(stderr,"%s","vcd_log_open_ctl == FALSE, not write log");
        return;
    }

    const int len_buf = 8000;
    char new_fmt[len_buf];
    memset(new_fmt,0,len_buf);

    #ifndef NDEBUG
    // debug 版本可以输出
    // 打印 文件名、行号、函数名
    snprintf(new_fmt, len_buf, "[%s %d %s] ", file, line, fun);
    #else
    sprintf(new_fmt,"%s",fmt);
    #endif

    va_list ap;
    va_start(ap, fmt);
    vsnprintf(new_fmt, len_buf, fmt, ap);
    va_end(ap);

#ifdef HAVE_LOG4C
    if(log_category)
        log4c_category_log(log_category, priority, "%s", new_fmt);
#else
    vcd_log_easylog(priority,new_fmt);
#endif
}

// ===  FUNCTION  ======================================================================
//  Name:  log_message
//  Description:  记录日志信息
//  @param priority [in]: 日志类别
//  @param file [in]: 文件
//  @param line [in]: 行
//  @param fun [in]: 函数
//  @param fmt [in]: 格式化参数
// =====================================================================================
void log_message_version_info(int priority, const char *file, int line, const char *fun, const char *fmt, ...)
{
    const int len_buf = 2000;
    char new_fmt[len_buf];
    char easy_buf[len_buf];
    int n = 0;

    n += snprintf(new_fmt + n, len_buf - n, "%s", fmt);

    va_list ap;
    va_start(ap, fmt);
    vsnprintf(easy_buf, len_buf, fmt, ap);
    va_end(ap);

#ifdef HAVE_LOG4C
    if(log_category_info)
        log4c_category_log(log_category_info, priority, "%s", easy_buf);
#else
    vcd_log_easylog(priority,easy_buf);
#endif
}


//int vcd_log_init(void)
//{
//    #define LOG4CRC_PATH "/etc/log4crc"

//    if (log4c_init() == 1) {
//        printf("linux log4c_init error!\n");
//        return -1;
//    }
//    init_dated_spice_format();
//    log4c_load(LOG4CRC_PATH);

//    log_category = log4c_category_get("vcdlog");
//    log_category_info = log4c_category_get("versioninfo");

//    //M_DEBUG("log4c init success, LOG4CRC_PATH:%s, ", LOG4CRC_PATH);
//    return 0;
//}

/**
 * @brief vcd_log_init_with_logdir
 * @param log4crc    配置文件路径
 * @param log_dir    log目录
 * @return
 *
 *    通过浏览器启动进程时,当前目录是浏览器的路径
 *    无法正常加载相对路径的配置文件，也无法确定配置文件中的相对路径
 *    所以配置文件和log目录使用绝对路径
 */
int vcd_log_init_with_logdir(const char* log4crc, const char* log_dir) {

#ifdef HAVE_LOG4C
    if (log4c_init() == 1) {
        printf("windows log4c_init error!\n");
        return -1;
    }

    init_dated_spice_format();
    log4c_load(log4crc);
    log_category = log4c_category_get("vcdlog");
    log_category_info = log4c_category_get("versioninfo");

    if (!log_dir) return 0;

    log4c_appender_t* app = log4c_appender_get("spicy");
    rollingfile_udata_t* rfup = rollingfile_make_udata();
    rollingfile_udata_set_logdir(rfup,log_dir);
    rollingfile_udata_set_files_prefix(rfup, "loginfo");
    log4c_rollingpolicy_t * rollingpolicyp = log4c_rollingpolicy_get("RollingPolicy");
    if (rollingpolicyp) {
        rollingfile_udata_set_policy(rfup, rollingpolicyp);
        log4c_appender_set_udata(app, rfup);
        log4c_rollingpolicy_init(rollingpolicyp, rfup);
    }

    app = log4c_appender_get("spicyinfo");
    rfup = rollingfile_make_udata();
    rollingfile_udata_set_logdir(rfup, log_dir);
    rollingfile_udata_set_files_prefix(rfup, "debug-version-info");
    rollingpolicyp = log4c_rollingpolicy_get("RollingPolicy1");
    if (rollingpolicyp) {
        rollingfile_udata_set_policy(rfup, rollingpolicyp);
        log4c_appender_set_udata(app, rfup);
        log4c_rollingpolicy_init(rollingpolicyp, rfup);
    }
#else
    vcd_log_init_easylog(log_dir);
#endif
    return 0;
}

int vcd_log_init_easylog(const char* logdir){
#ifdef __linux__
    struct timeval start;
    gettimeofday(&start, NULL);
    struct tm t;
    bzero(&t, sizeof(t));
    localtime_r(&start.tv_sec, &t);

    char buf[100] = {0};
    if(g_vcd_log_filename)
        sprintf(buf, "%s/%s-%04d-%02d-%02d.log", logdir,g_vcd_log_filename,t.tm_year + 1900, t.tm_mon + 1, t.tm_mday);
    else
        sprintf(buf, "%s/vclient-%04d-%02d-%02d.log", logdir,t.tm_year + 1900, t.tm_mon + 1, t.tm_mday);

    easylog_file(buf);
    easylog_flag_add(EASYLOG_DATE|EASYLOG_TIME|EASYLOG_LEVEL);

    _vcd_log_delete_old_log(logdir);
#endif
    return 0;
}

void vcd_log_easylog(int level,const char* log){
#ifdef __linux__

    switch (level) {
    case LOG_PRIORITY_DEBUG:
        if( g_debug_flag)
            easylog_debug("%s",log);
        break;
    case LOG_PRIORITY_INFO:
    case LOG_PRIORITY_WARN:
        easylog_info("%s",log);
        break;
    case LOG_PRIORITY_ERROR:
        easylog_err("%s",log);
        break;
    default:
        fprintf(stderr,"default-log: %s",log);
        break;
    }
#endif
}

void vcd_log_set_debug_flag(gboolean b){
    g_debug_flag = b;
}

void vcd_log_set_filename(char* name){
    if(g_vcd_log_filename)
        free(g_vcd_log_filename);
    g_vcd_log_filename = strdup(name);
}

static void _vcd_log_delete_old_log(const char* logdir){
#ifdef __linux
    // find /var/log/ -mtime +7 -name "vclient-*.log" -exec rm -rf {} \;
    //const char* cmd = "find /var/log/ -mtime +7 -name \"vclient-*.log\" -exec rm -rf {} \\;";

    char cmd_buf[100] = {0};
    const char* fmt = "find %s -mtime +7 -name \"vclient-*.log\" -exec rm -rf {} \\;";
    sprintf(cmd_buf,fmt,logdir);

    system(cmd_buf);
#endif
}




